#define OPEN_DEBUG_SKILL
#if OPEN_DEBUG_SKILL && UNITY_EDITOR
#define DEBUG_SKILL
#endif
using System;
using System.Collections.Generic;
using Lockstep.Collision2D;
using Lockstep.Game;
using Lockstep.Math;
using Lockstep.Game;
#if UNITY_EDITOR
using UnityEngine;
#endif
using Debug = Lockstep.Logging.Debug;


public enum ESkillState
{
    Idle,
    Firing,
}

namespace Lockstep.Game
{
    public interface ISkillEventHandler
    {
        void OnSkillStart(Skill skill);
        void OnSkillDone(Skill skill);
        void OnSkillPartStart(Skill skill);
    }

    [Serializable]
    public partial class Skill : INeedBackup
    {
        [ReRefBackup] public ISkillEventHandler eventHandler;
        [ReRefBackup] public Entity entity { get; private set; }
        [ReRefBackup] public SkillInfo SkillInfo;

        public LFloat CdTimer;
        public ESkillState State;
        public LFloat skillTimer;
        public int[] partCounter = new int[0];
        [Backup] private int _curPartIdx;

        public SkillPart CurPart => _curPartIdx == -1 ? null : Parts[_curPartIdx];
#if DEBUG_SKILL
        private float _showTimer;
#endif

        public LFloat CD => SkillInfo.CD;
        public LFloat DoneDelay => SkillInfo.doneDelay;
        public List<SkillPart> Parts => SkillInfo.parts;
        public EColliderLayer TargetLayer => SkillInfo.targetLayer;
        public LFloat MaxPartTime => SkillInfo.maxPartTime;
        public string AnimName => SkillInfo.animName;

        public void ForceStop() { }

        public void BindEntity(Entity entity, SkillInfo info, ISkillEventHandler eventHandler)
        {
            this.entity = entity;
            this.SkillInfo = info;
            this.eventHandler = eventHandler;
        }

        public void DoStart()
        {
            skillTimer = MaxPartTime;
            State = ESkillState.Idle;
            _curPartIdx = -1;
            partCounter = new int[Parts.Count];
        }


        public bool Fire()
        {
            if (CdTimer <= 0 && State == ESkillState.Idle)
            {
                CdTimer = CD;
                skillTimer = LFloat.zero;
                for (int i = 0; i < partCounter.Length; i++)
                {
                    partCounter[i] = 0;
                }

                State = ESkillState.Firing;
                entity.animator?.Play(AnimName);
                OnFire();
                return true;
            }

            return false;
        }

        public void OnFire()
        {
            eventHandler.OnSkillStart(this);
        }

        public void Done()
        {
            eventHandler.OnSkillDone(this);
            State = ESkillState.Idle;
            entity.animator?.Play(AnimDefine.Idle);
        }

        public void DoUpdate(LFloat deltaTime)
        {
            CdTimer -= deltaTime;
            skillTimer += deltaTime;
            if (skillTimer < MaxPartTime)
            {
                for (int i = 0; i < Parts.Count; i++)
                {
                    var part = Parts[i];
                    CheckSkillPart(part, i);
                }

                foreach (var part in Parts) { }
            }
            else
            {
                _curPartIdx = -1;
                if (State == ESkillState.Firing)
                {
                    Done();
                }
            }
        }

        void CheckSkillPart(SkillPart part, int idx)
        {
            if (partCounter[idx] > 0) return;
            if (skillTimer > part.startTimer)
            {
                TriggerPart(part, idx);
                partCounter[idx]++;
            }
        }

        void TriggerPart(SkillPart part, int idx)
        {
            eventHandler.OnSkillPartStart(this);
            _curPartIdx = idx;
#if DEBUG_SKILL
            _showTimer = Time.realtimeSinceStartup + 0.1f;
#endif
            if (part.type == SkillPartType.Bullet) {
                if (part.bulletConfig.type == BulletType.NormalLine) { 
                    BulletEntity bullet = entity.GameStateService.CreateBullet<NormalLineBullet>(part.bulletConfig, entity, (entity.transform.pos + entity.transform.forward * entity.colliderData.radius).ToLVector3());
                }
            }
        }

    }
}